<?php


class curlflickr{	
//this class help to use flickr as a image hosting server
	//the main functions are uploadsingle and umulty which you should focus	
	//you must set the follow keys yourself
   var $api_key="";//flickr api key for the app
   var $secret="";//flickr api secret code for the app
   var $auth_token="";//session after login
   
   
   //optional settiong keys  below
   var $api_sig=""; 
   var $sessionname="flickr_session_upload";////when change/new api , call auth first to get a session
   
   var $uploadurl="http://api.flickr.com/services/upload/";//do not change unless you know what you're doing 

   var $post=array();//store the post data
   
   var $err=array();//store errormessage
   var $size=TRUE;//if false , will using get info which will only return url but without size
                  //you set $this->size to false only if you like to have a not good way and have troble , but i don't think will help
   var $singletimeout=10;				  
   var $multitimeout=30;//set larger if lots of photo upload at a same time
   
   function umulty($images,$size="large",$title = array(), $description = array(), $tags = array(), $is_public = array(), $is_friend = array(), $is_family = array()){
		   $res=$this->uploadmulti($images);
	   $pids=$this->cmiphotoid($res,TRUE);
	   $infos=$this->cmiphotoinfo($pids);
	   foreach($infos as $key=>$info){
		  $urls[$key]=$this->buildPhotoURL($info,$size);  //all,array,large,small,square,thumbnail,medium is all ok
		  //print "<img src='".$url."' /><br />";
	   }
	   $infos=NULL;$pids=NULL;$res=NULL;
	   return $urls;
   }
   
   function uploadsingle($photopath,$size="large",$title = NULL, $description = NULL, $tags = NULL, $is_public = NULL, $is_friend = NULL, $is_family = NULL){
	   //this is just a wrapper function to upload a pictures easyly
	   $photoid=$this->uploadone($photopath,$title, $description, $tags, $is_public, $is_friend, $is_family);
	   if(!$this->size){
		 $obj=$this->photos_getInfo($photoid);	
		 return $this->buildPhotoURL($obj,$size);
		 //print_r($obj);	 
	   }else{//default way
		  $obj=$this->photos_getInfo($photoid,"flickr.photos.getSizes","sizes");	
		  return $this->buildPhotoURL($obj,$size);		  
	   }
   }
      		      
   
   function auth($perms="write",$message=FALSE){
	  session_start(); 
	  if(empty($_SESSION[$this->sessionname])){
			  
		  if(empty($_GET["frob"])){
		  $post=array(
			 "method" => "flickr.auth.getToken",
			 "format" => "php_serial",
			 "api_key" => $this->api_key,
		  );
		  
		  $redirect = $_SERVER['REQUEST_URI'];
		  
		  $api_sig=md5($this->secret."api_key".$this->api_key."extra".$redirect."perms".$perms);
		  
		  header("Location: http://www.flickr.com/services/auth/?api_key=" . $this->api_key . "&extra=" . $redirect . "&perms=" . $perms . "&api_sig=". $api_sig);
		  exit();
	  }else{
		$post=array(
			 "method" => "flickr.auth.getToken",
			 "format" => "php_serial",
			 "api_key" => $this->api_key,
			 "frob"=>$_GET["frob"],
		  );
		 ksort($post);
		  $t="";
		  foreach($post as $key=>$field){
			 $t.=$key.$field;	
		  }
		  $api_sig=md5($this->secret.$t);
		  $post["api_sig"]=$api_sig;
		  $ch=curl_init();
		  $headerfor[]='Connection: Keep-Alive';
		  curl_setopt($ch, CURLOPT_HTTPHEADER,$headerfor); 
		  curl_setopt($ch, CURLOPT_URL, "http://api.flickr.com/services/rest/");
		  curl_setopt($ch, CURLOPT_POST,1);
		  curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
		  curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 
		   curl_setopt($ch, CURLOPT_TIMEOUT, $this->singletimeout);
		  $s=curl_exec($ch);		
		  curl_close($ch);
		  $s=unserialize($s);
		  
		  if(!isset($_SESSION[$this->sessionname])){
			session_register($this->sessionname);		  
		  }else{
			print "success!your last session is still ok   ".$this->sessionname." and its content is ".$_SESSION[$this->sessionname]."just do the upload job,have fun";
			return;
		  }
		  if(!empty($s[auth][token][_content])){
			 $_SESSION[$this->sessionname]=$s[auth][token][_content];
			 $this->auth_token=$_SESSION[$this->sessionname];
			 if($message){
				print_r($s);
				print "successfully login and the session name is   ".$this->sessionname." and its content is ".$_SESSION[$this->sessionname];
			 }
		  }else{
			 print_r($s);
			 $this->err[]="login failed , check your apikey and secret code both please";
			 $this->error();
			 exit;
		  }
		  
		  
		} 
	  }else{
		  if($message){
				print "success!your last session is still ok   ".$this->sessionname." and its content is ".$_SESSION[$this->sessionname]."just do the upload job,have fun";
			 }
	  }
   }//function auth
   
   function curlflickr($api_key=NULL,$secret=NULL,$sessionname=NULL){//construct function
      /*
       if(!empty($api_key) && !empty($_SESSION[$this->sessionname]) ){
		   $this->sessionname=$sessionname;  
	   }
	   if(empty($_SESSION[$this->sessionname])){	   
	   //$this->err[]="we need to login to flickr firstly,please call \$objname->auth() method and then do your next jobs;\nwe reconnize your run tw0 line only first:\n\$fr=new curlflickr('flickr-apikey','flickr-secret');\n\$fr->auth();\nand then follow the page";  
		  $this->auth();
	   }
	   */
       if(!empty($api_key))
	   $this->api_key=$api_key;
	    if(!empty($secret))
	   $this->secret=$secret;
	  if(!empty($sessionname))
	   $this->sessionname=$sessionname;
	   
   }   
   
   function genpost($fields=array()){ // a helper function to generate post data
     session_start(); 
		if(!empty($_SESSION[$this->sessionname])){
		 $this->auth_token=$_SESSION[$this->sessionname];
		}
	 if(!isset($this->post['auth_token']) || !isset($this->post['api_key'])){
		if(empty( $this->api_key)|| empty($this->auth_token)){
		  $this->err[]="you're missing key api_key or auth_token, in the case api_key , you should set in either $objectname->api_key or new curlflickr($api_key);if auth_token,you should login to yahoo flickr first";	
		  $this->error();
		  exit();
		}
	  $post=array(
		  "api_key" => $this->api_key,
		  "auth_token" => $this->auth_token,		  
		  );	    
	 }
	 if(!empty($fields)){
		  foreach($fields as $key=> $field){
			  if(!empty($field))
			  $post[$key]=$field;
		  }
	 }
	 return $post;
   }
   
  
   
   function gensig($post){//a helper function to generate api_sig
	  ksort($post);
	  $t="";
	  foreach($post as $key=>$field){
		  if(strtoupper($key)!="API_SIG" && strtoupper($key)!="PHOTO" && !is_null($field) && trim($field)!="")
		  $t.=$key.$field;	
	  }
	  $api_sig=md5($this->secret.$t);
	  $post["api_sig"]=$api_sig;
	  return $post;
   }
   
	function uploadone($photopath=NULL,$title = NULL, $description = NULL, $tags = NULL, $is_public = NULL, $is_friend = NULL, $is_family = NULL){//upload just only one picture
	    if(empty($photopath)){
			 $this->err[]="missing photopath to upload when using uploadone method,you should use it like \$objname->uploadone('/path/to/photo.jpg')";
		 $this->error();
		 exit();
		}
	    $this->post=$this->genpost(array("title" => $title, "description" => $description, "tags" => $tags, "is_public" => $is_public, "is_friend" => $is_friend, "is_family" => $is_family));	
		
		//core function happen here
		$ch=curl_init();
		curl_setopt($ch, CURLOPT_URL, $this->uploadurl);
		curl_setopt($ch, CURLOPT_POST,1);
		curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 
		$this->post=$this->gensig($this->post);
		curl_setopt($ch, CURLOPT_TIMEOUT, $this->singletimeout);
		
		  $this->post["photo"]="@".realpath($photopath);//@+realpath
		
		curl_setopt($ch, CURLOPT_POSTFIELDS,$this->post);		
		$s=curl_exec($ch);
		curl_close($ch);
		$s=$this->photoid($photopath,$s);				
		return $s;
	}
	
	function uploadmulti($connomains=array(),$title = array(), $description = array(), $tags = array(), $is_public = array(), $is_friend = array(), $is_family = array()){
		//$connomains is image array
		if(empty($connomains)){
			 $this->err[]="missing photopath to upload when using uploadmulti method,you should use it like the example";
		 $this->error();
		 exit();
		}
		 $res=array();			
    		$mh = curl_multi_init();						
    		foreach ($connomains as $i => $url) {
				$post=$this->genpost(array("title" => $title[$i], "description" => $description[$i], "tags" => $tags[$i], "is_public" => $is_public[$i], "is_friend" => $is_friend[$i], "is_family" => $is_family[$i]));	
		
				 $conn[$url]=curl_init();
		         curl_setopt($conn[$url], CURLOPT_URL, $this->uploadurl);    			 				 
    			 curl_setopt($conn[$url], CURLOPT_TIMEOUT, $this->multitimeout);//change this if you want to have  huge images
    			 curl_setopt($conn[$url], CURLOPT_POST,1);
		          curl_setopt($conn[$url],CURLOPT_RETURNTRANSFER,1); 
				  
				  $post=$this->gensig($post);
		          $post["photo"]="@".realpath($url);//@+realpath	
				  //print_r($post);//debug
				 curl_setopt($conn[$url], CURLOPT_POSTFIELDS,$post);				
    			  // curl_setopt($conn[$url], CURLOPT_FOLLOWLOCATION, TRUE);
    			  curl_multi_add_handle ($mh,$conn[$url]);				  
				  
    		}
    		
    		do {
    				$mrc = curl_multi_exec($mh,$active);
    		} while ($mrc == CURLM_CALL_MULTI_PERFORM);
    		while ($active and $mrc == CURLM_OK) {
    				if (curl_multi_select($mh) != -1) {
    						do {
    								$mrc = curl_multi_exec($mh, $active);
    						} while ($mrc == CURLM_CALL_MULTI_PERFORM);
    				}
    		}

    		foreach ($connomains as $i => $url) { 
			   //$cinfo=curl_getinfo($conn[$url]);//debug
			   //print_r($cinfo);//debug
					  $res[$url]=curl_multi_getcontent($conn[$url]);//return 				 			  
				   curl_close($conn[$url]);
                  curl_multi_remove_handle($mh  , $conn[$url]);         			       			 
    		} 
    		curl_multi_close($mh);$mh=NULL;$conn=NULL;$connomains=NULL;      	
    		return $res;		
	}
	function cmiphotoid($res,$debug=FALSE){
		$result=array();
	  foreach($res as $ori=>$s){
		if(@preg_match("/photoid>([^<]*)</i",$s,$match)){
			$result[$ori]=$match[1];
		}else{
			$this->err[]="could not upload file ".$ori." ,or upload picture not exist,or  check your account if i have exceed flickr limit')";		    
		}
	  }
	  if($debug) $this->error();
	  return $result;
	  
	}
	
	function cmiphotoinfo($photoids){	
	   
		  //print_r($photoids);
		 $res=array();			
    		$mh = curl_multi_init();						
    		foreach ($photoids as $i => $url) {
				if(!$this->size){
				  $post=$this->photoinfopost($photoids[$i]);
				}else{
				  $post=$this->photoinfopost($photoids[$i],"flickr.photos.getSizes");
				}
				 $conn[$i]=curl_init();
				  $headerfor[]='Connection: Keep-Alive';
		          curl_setopt($conn[$i], CURLOPT_HTTPHEADER,$headerfor); 
		         curl_setopt($conn[$i], CURLOPT_URL, "http://api.flickr.com/services/rest/");    			 				 
    			 curl_setopt($conn[$i], CURLOPT_TIMEOUT, $this->multitimeout);
    			 curl_setopt($conn[$i], CURLOPT_POST,1);
				 curl_setopt($conn[$i], CURLOPT_POSTFIELDS,$post);
		          curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1); 				  				  
    			  
    			  curl_multi_add_handle ($mh,$conn[$i]);				  
				  
    		}
    		
    		do {
    				$mrc = curl_multi_exec($mh,$active);
    		} while ($mrc == CURLM_CALL_MULTI_PERFORM);
    		while ($active and $mrc == CURLM_OK) {
    				if (curl_multi_select($mh) != -1) {
    						do {
    								$mrc = curl_multi_exec($mh, $active);
    						} while ($mrc == CURLM_CALL_MULTI_PERFORM);
    				}
    		}

    		foreach ($photoids as $i => $url) { 
			   //$cinfo=curl_getinfo($conn[$url]);//debug
			   //print_r($cinfo);//debug
					  $r=curl_multi_getcontent($conn[$i]);//return 
					  $r=unserialize($r);
					  if(!$this->size){
					    $res[$i]=$r[photo];
					  }else{
						 $res[$i]=$r[sizes];  
					  }
				   curl_close($conn[$i]);
                  curl_multi_remove_handle($mh  , $conn[$i]);         			       			 
    		} 
    		curl_multi_close($mh);$mh=NULL;$conn=NULL;$photoids=NULL;      	
    		return $res;		
		
		
	}
	
	function photos_getInfo($photo_id,$method="flickr.photos.getInfo",$ori="photo") {//"flickr.photos.getSizes" is better $ori="sizes"
	    $post=$this->photoinfopost($photo_id,$method);
		//print_r($post);
		$ch=curl_init();
		  $headerfor[]='Connection: Keep-Alive';
		  curl_setopt($ch, CURLOPT_HTTPHEADER,$headerfor); 
		  curl_setopt($ch, CURLOPT_URL, "http://api.flickr.com/services/rest/");
		  curl_setopt($ch, CURLOPT_POST,1);
		  curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
		  curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 
		  curl_setopt($ch, CURLOPT_TIMEOUT, $this->singletimeout);
		  $s=curl_exec($ch);		
		  curl_close($ch);
		  $post=NULL;	
		  $s=unserialize($s);
		  $s=$s[$ori];		  
		  return $s;		  
	}
	
	

	function photoinfopost($photo_id,$method="flickr.photos.getInfo"){//"flickr.photos.getSizes" is better
		session_start(); 
		 $post=array(
			 "method" => $method,
			 "format" => "php_serial",
			 "api_key" => $this->api_key,
			 "photo_id" => $photo_id,
		  );
		 if (!empty($this->auth_token)) {
			 $post[auth_token] = $this->token;
		  } elseif (!empty($_SESSION[$this->sessionname])) {
			 $post[auth_token] =  $_SESSION[$this->sessionname];
		  }
		  ksort($post);		 
		  $t="";
		  foreach($post as $key=>$field){			  
			  $t.=$key.$field;	
		  }
		  $api_sig=md5($this->secret.$t);
		  $post["api_sig"]=$api_sig;
		  return $post;
	}
	
	function photoid($ori,$s){		
		if(@preg_match("/photoid>([^<]*)</i",$s,$match)){
			return $s=$match[1];
		}else{
			$this->err[]="could not upload file ".$ori." ,or upload picture not exist,or  check your account if i have exceed flickr limit')";
		    $this->error();
		}				
	}
	
	 function error(){
		$output="<div style='color:red'>" ;
	   foreach($this->err as $e){
	     $output.= $e."<br />";
	   }
	   $output.="</div>";
	   print $output;
	   //trigger_error("error happen,check the above message");
   }
   
   function buildPhotoURL ($photo, $size = "Medium") {//it's no used
	    //large will only be exist if the photo is large
		//receives an array (can use the individual photo data returned
		//from an API call) and returns a URL (doesn't mean that the
		//file size exists)
	if(!$this->size){	
				$sizes = array(
					"square" => "_s",
					"thumbnail" => "_t",
					"small" => "_m",
					"medium" => "",
					"large" => "_b",
					"original" => "_o",//only used to pay user
					//"array"=>"yes";//just a flag to tell return an array of all urls
				);		
				if(strtolower($size)!="array"){
				  $size = strtolower($size);
				  if (!array_key_exists($size, $sizes)) {
					  $size = "medium";
				  }
				 //print_r($photo);
				  
				  if ($size == "original") {
					  $url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['originalsecret'] . "_o" . "." . $photo['originalformat'];
				  } else {
					  $url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['secret'] . $sizes[$size] . ".jpg";
				  }
				  print $url;
				  return $url;
				}else{//return an array
				   $result=array();
					foreach($sizes as $size=>$key){
						$size = strtolower($size);				
						if ($size == "original") {
							$url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['originalsecret'] . "_o" . "." . $photo['originalformat'];
						} else {
							$url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['secret'] . $sizes[$size] . ".jpg";
						}
						$result[$size]=$url;				
					}//foreach		  	
					return $result;
				}//if array
      }else{
		  //print_r($photo);exit;
		  $sizes=$photo[size];
		  $result=array();
		  foreach($sizes as $siz){
			$result[strtolower($siz[label])]=$siz[source];						  
		  }
		  if(strtolower($size)=="array"){
		    return $result;
		  }elseif(strtolower($size)=="all"){
			  return $sizes;
		  }else{			   
		      return $result[$size];
		  }
	  }
   }

}




?>